package login_service

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"time"

	"github.com/EDDYCJY/go-gin-example/middleware/jwt"
	"github.com/EDDYCJY/go-gin-example/models"
	"github.com/EDDYCJY/go-gin-example/pkg/alibaba"
	"github.com/EDDYCJY/go-gin-example/pkg/app"
	"github.com/EDDYCJY/go-gin-example/pkg/logging"
)

// Login 定义登录请求结构体
type Login struct {
	State string `alias:"三方参数" form:"state"  json:"state" valid:"Required;"`
	Code  string `alias:"code" form:"code"  json:"code" valid:"Required;"`
}

type aliTokenMsg struct {
	AccessToken         string `json:"access_token"`
	AliID               string `json:"aliId"`
	RefreshToken        string `json:"refresh_token"`
	ResourceOwner       string `json:"resource_owner"`
	ExpiresIn           string `json:"expires_in"`
	RefreshTokenTimeout string `json:"refresh_token_timeout"`
	MemberID            string `json:"memberId"`
}

// Login 执行用户登录逻辑
func (t *Login) Login() (map[string]interface{}, error) {

	url := alibaba.DefaultHost + "http/1/system.oauth2/getToken/" + alibaba.AppKey + "?grant_type=authorization_code&need_refresh_token=true&client_id=" + alibaba.AppKey + "&client_secret=" + alibaba.AppSecret + "&redirect_uri=&code=" + t.Code
	info, _ := app.HttPPOst(url, "")
	var aliInfo aliTokenMsg
	json.Unmarshal([]byte(info), &aliInfo)
	if aliInfo.AccessToken == "" {
		logging.Info("alitoken", "获取token失败", info)
		return nil, errors.New("获取token失败")
	}
	// 1. 查询用户信息
	userInfo, err := models.GetUserInfo([]string{"user_id", "user_name"}, map[string]interface{}{
		"ali_id": aliInfo.AliID,
	})
	if err != nil {
		return nil, fmt.Errorf("系统错误，请稍后重试")
	}
	// 2. 验证用户是否存在
	if userInfo.UserId == 0 {
		ExpiresIn, _ := strconv.ParseInt(aliInfo.ExpiresIn, 0, 64)
		AliID, _ := strconv.ParseInt(aliInfo.AliID, 0, 64)
		//3. 创建用户
		UserId, err := models.AddUser(map[string]interface{}{
			"ali_id":                int(AliID),
			"member_id":             aliInfo.MemberID,
			"refresh_token":         aliInfo.RefreshToken,
			"access_token":          aliInfo.AccessToken,
			"refresh_token_timeout": aliInfo.RefreshTokenTimeout,
			"expires_in":            int(time.Now().Unix()) + int(ExpiresIn),
			"resource_owner":        aliInfo.ResourceOwner,
			"user_name":             aliInfo.ResourceOwner,
		})
		if err != nil {
			return nil, fmt.Errorf("系统错误，请稍后重试")
		}
		userInfo.UserId = UserId
		userInfo.UserName = aliInfo.ResourceOwner
	}

	// 4. 生成 JWT Token
	accessToken, refreshToken := jwt.GenToken(userInfo.UserId, userInfo.UserId)
	if err != nil {
		return nil, fmt.Errorf("系统s错误，请稍后重试")
	}

	// 6. 返回登录结果
	return map[string]interface{}{
		"user_id":       userInfo.UserId,
		"user_name":     userInfo.UserName,
		"access_token":  accessToken,
		"refresh_token": refreshToken,
	}, nil
}

// RefreshToken 定义登录请求结构体
type RefreshToken struct {
	AccessToken string
	Refresh     string
}

func (t *RefreshToken) RefreshToken() (map[string]interface{}, error) {
	res, claim, err := jwt.Expired(t.AccessToken)
	if res {
		// 将id和salt和时间戳连接起来
		toHash := claim.Jti + jwt.HASH_SALT + strconv.Itoa(claim.Iat)
		// fmt.Printf("toHash%v\n", toHash)

		// 计算toHash的SHA256哈希
		h := sha256.New()
		h.Write([]byte(toHash))
		hashed := h.Sum(nil)
		// 将哈希转换为十六进制字符串
		refreshToken := hex.EncodeToString(hashed)

		if refreshToken != t.Refresh {
			return nil, errors.New("refresh_token 不匹配")
		} else {
			accessToken, refreshToken := jwt.GenToken(claim.UID, claim.Aid)
			return map[string]interface{}{
				"access_token":  accessToken,
				"refresh_token": refreshToken,
			}, nil
		}
	} else {
		return nil, err
	}
}

type AliRefreshToken struct {
}

func (t *AliRefreshToken) AliRefreshToken() (map[string]interface{}, error) {
	// 1. 查询用户信息
	err := refreshUserTokens()
	if err != nil {
		return nil, err
	}
	return nil, nil
}

// 1. 定义每批处理的用户数量
const batchSize = 100

// 2. 查询用户信息并分批处理
func refreshUserTokens() error {
	// 查询需要刷新的用户列表
	userList, err := models.GetUser([]string{"user_id", "user_name", "refresh_token", "access_token"}, map[string]interface{}{
		"expires_in <": time.Now().Add(+time.Hour * 1).Unix(),
	})
	if err != nil {
		logging.Info("goods.go", "查询用户信息失败", "error", err.Error())
		return fmt.Errorf("系统错误，请稍后重试")
	}

	// 分批处理用户列表
	for i := 0; i < len(userList); i += batchSize {
		end := i + batchSize
		if end > len(userList) {
			end = len(userList)
		}
		batch := userList[i:end]

		// 处理当前批次的用户
		if err := processUserBatch(batch); err != nil {
			logging.Info("goods.go", "处理用户批次失败", "batch_index", i, "error", err.Error())
			return err
		}
	}

	logging.Info("goods.go", "用户Token刷新完成", "total_users", len(userList))
	return nil
}

// 3. 处理单个批次的用户
func processUserBatch(users []*models.User) error {
	for _, user := range users {
		// 刷新Token
		tokenInfo, err := refreshToken(user.RefreshToken)
		if err != nil {
			logging.Info("goods.go", "刷新Token失败", "user_id", user.UserId, "error", err.Error())
			continue // 跳过当前用户，继续处理下一个
		}

		// 更新用户Token信息
		if err := updateUserToken(user.UserId, tokenInfo); err != nil {
			logging.Info("goods.go", "更新用户Token失败", "user_id", user.UserId, "error", err.Error())
			continue
		}

		logging.Info("goods.go", "用户Token刷新成功", "user_id", user.UserId)
	}
	return nil
}

// 4. 刷新Token
func refreshToken(refreshToken string) (alibaba.AliDecryptJsons, error) {
	params := map[string]string{
		"client_id":     alibaba.AppKey,
		"client_secret": alibaba.AppSecret,
		"refresh_token": refreshToken,
		"grant_type":    "refresh_token",
	}
	method := "system.oauth2:getToken"
	tokenInfo, err := alibaba.GetAlibabaAPI(method, params)
	if err != nil {
		return alibaba.AliDecryptJsons{}, err
	}
	return tokenInfo, nil
}

// 5. 更新用户Token信息
func updateUserToken(userId int, tokenInfo alibaba.AliDecryptJsons) error {
	maps := map[string]interface{}{
		"user_id": userId,
	}
	update := map[string]interface{}{
		"access_token": tokenInfo.AccessToken,
	}
	expires, err := strconv.ParseInt(tokenInfo.ExpiresIn, 0, 64)
	if err != nil {
		return err
	}
	update["expires_in"] = int(time.Now().Unix()) + int(expires)
	return models.EditUser(maps, update)
}

// Login 定义登录请求结构体
type DyLogin struct {
	State string `alias:"三方参数" form:"state"  json:"state" valid:"Required;"`
	Code  string `alias:"code" form:"code"  json:"code" valid:"Required;"`
}

// DyLogin 执行用户登录逻辑
func (t *DyLogin) DyLogin() (map[string]interface{}, error) {
	// res, err := douyin.GetDouyinToken(t.Code)

	// models
	// 6. 返回登录结果
	return nil, nil
}
